package cn.orangeframe.neon.application.command;

import cn.orangeframe.neon.application.run.WorkflowExecutor;
import cn.orangeframe.neon.domain.entity.GraphData;
import cn.orangeframe.neon.infrastructure.convertor.GraphToWorkflow;
import com.alibaba.fastjson2.JSON;
import cn.orangeframe.neon.domain.adapter.MetadataAdapter;
import cn.orangeframe.neon.domain.entity.WorkflowDef;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

@Component
public class MetadataCommand {

    private final MetadataAdapter metadataAdapter;

    private final WorkflowExecutor executor;

    public MetadataCommand(MetadataAdapter metadataAdapter, WorkflowExecutor executor) {
        this.metadataAdapter = metadataAdapter;
        this.executor = executor;
    }

    /**
     * Register or update a workflow definition.
     * @param workflowDef The workflow definition to register or update.
     */
    public void registerOrUpdate(WorkflowDef workflowDef) {
        WorkflowDef current = metadataAdapter.getWorkflowDef(workflowDef.getName(), workflowDef.getVersion());
        Integer latestVersion = metadataAdapter.getLatestVersion(workflowDef.getName());
        if (current == null) {
            latestVersion= latestVersion == null ? workflowDef.getVersion() : Math.max(workflowDef.getVersion(), latestVersion) ;
            metadataAdapter.registerWorkflowDef(workflowDef, latestVersion, JSON.toJSONString(workflowDef));
        } else {
            metadataAdapter.updateWorkflowDef(workflowDef, latestVersion, JSON.toJSONString(workflowDef));
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void registerOrUpdateGraph(GraphData graphWorkflowDef) {
        WorkflowDef workflowDef = GraphToWorkflow.convert(graphWorkflowDef);
        graphWorkflowDef.setName(workflowDef.getName());
        graphWorkflowDef.setVersion(workflowDef.getVersion());
        GraphData current = metadataAdapter.getGraphWorkflowDef(graphWorkflowDef.getName(), graphWorkflowDef.getVersion());
        Integer latestVersion = metadataAdapter.getLatestVersion(graphWorkflowDef.getName());
        if (current == null) {
            latestVersion= latestVersion == null ? graphWorkflowDef.getVersion() : Math.max(graphWorkflowDef.getVersion(), latestVersion) ;
            metadataAdapter.registerGraphWorkflowDef(graphWorkflowDef, latestVersion, JSON.toJSONString(graphWorkflowDef));
        } else {
            metadataAdapter.updateGraphWorkflowDef(graphWorkflowDef, latestVersion, JSON.toJSONString(graphWorkflowDef));
        }
        registerOrUpdate(workflowDef);
    }

    /**
     * 根据流程名和版本获取流程定义
     * @param name 流程名
     * @param version 流程版本
     * @return 流程定义
     */
    public WorkflowDef getWorkflowDef(String name, Integer version) {
        return metadataAdapter.getWorkflowDef(name, version);
    }

    /**
     * 根据流程名和版本获取流程定义
     * @param name 流程名
     * @param version 流程版本
     * @return 流程定义
     */
    public GraphData getGraphWorkflowDef(String name, Integer version) {
        return metadataAdapter.getGraphWorkflowDef(name, version);
    }

    /**
     * 根据流程名获取最新版本的流程定义
     * @return 流程定义列表
     */
    public List<WorkflowDef> getWorkflowDefList() {
        return metadataAdapter.getAllWorkflowDef();
    }

    /**
     * 开始流程
     * @param name 流程名
     * @param version 流程版本
     * @param input 流程输入参数
     * @return 流程输出参数
     */
    public Map<String, Object> startWorkflow(String name, Integer version, Map<String, Object> input) {
        return executor.startWorkflowWithOutput(name, version, input);
    }
}
